// src/pages/videoDetail/index.tsx
import React, { useEffect, useRef, useState, useMemo } from 'react';
import Taro, { useRouter, usePullDownRefresh, useDidShow } from '@tarojs/taro';
import {
  View,
  Swiper,
  SwiperItem,
  Video,
  Text,
  Image,
  Slider,
  Button,
} from '@tarojs/components';
import './index.less';
import TitleBar from '@/src/components/titleBar';
import store from '@/src/store';
import { observer } from 'mobx-react-lite';
import collectIcon from '../../assert/imgs/vedio/collect.png';
import collectedIcon from '../../assert/imgs/vedio/collected.png';
import share from '../../assert/imgs/vedio/share.png';
import fullscreen from '../../assert/imgs/vedio/fullScreen.png';
import {
  addCollectionFun,
  cancelCollectionFun,
  queryInfoFun,
  videoRecommendFun,
} from '@/src/common/method/homeFun';
import { getNetWorkStatus } from '@/src/common/util/util';
import { netWorkErrorInfo } from '@/src/utils/constants';
import { showToast, StatusToast } from '@/src/components/statusToast';
import { halfScreenJump } from '@/src/utils/halfScreen';
import { isLoginFun } from '@/src/common/method/commonFun';

type RouteParams = Partial<
  Record<'contentId' | 'contentKind' | 'contentType' | 'from', string>
>;
type VideoCtx = ReturnType<typeof Taro.createVideoContext>;
// iOS 上更容易出现“画面动但无声”
const isIOS =
  store.commonStore.isIos ??
  /iOS|iPhone|iPad/i.test(Taro.getSystemInfoSync().system || '');
const PLAY_DEBOUNCE = isIOS ? 120 : 0;

//一页请求的数量
const PAGE_SIZE = 10;
// 滑到倒数第 N 个开始预取下一页，避免等待
const PREFETCH_OFFSET = 3;
const getItemId = (it: any) =>
  it?.contentId || it?.contentVideoId || it?.id || '';

// 屏幕尺寸与最小高度（px）
const { windowWidth, windowHeight } = Taro.getSystemInfoSync();
const MIN_HEIGHT_PX = Math.max(220, Math.round(windowHeight * 0.25)); // 自行按需调整

//  窗口保留的左右范围（只渲染 current±1）
const V_KEEP_LEFT = 1;
const V_KEEP_RIGHT = 1;
let clickAble = true;

//  长刷时的“裁头”策略，防止列表无限增长
const DROP_THRESHOLD = 12; // 当前索引超过该阈值时触发裁剪
const DROP_BATCH = 8; // 每次裁掉的条数（根据 UI/体验可调整）

const VideoDetail: React.FC = () => {
  const [current, setCurrent] = useState(0);
  const { params } = useRouter<RouteParams>();

  // —— 核心数据：视频渲染列表（首条详情 + 推荐分页追加） —— //
  const [vedioInfoList, setVedioInfoList] = useState<any[]>([]);

  // 分页 & 加载状态（pageNo 从 0 开始；首条详情不算页）
  const [pageNo, setPageNo] = useState(0);
  const [hasMore, setHasMore] = useState(true);
  const [loadingMore, setLoadingMore] = useState(false);
  const [refreshing, setRefreshing] = useState(false);
  //最小内容id-视频
  const [minContentVideoId, setMinContentVideoId] = useState<string>('');
  const [collect, setCollect] = useState(false); //收藏状态
  // 记录当前处于全屏的视频索引（不在全屏则为 null）
  const [fullscreenIdx, setFullscreenIdx] = useState<number | null>(null);
  // 顶部 state 增加一个播放状态映射
  const [playingMap, setPlayingMap] = useState<Record<number, boolean>>({});
  // 仅渲染当前±1，减少同屏 video 数量，避免卡顿
  // 审核状态值true为通过，false是不通过
  const [auditStatusVal, setAuditStatusVal] = useState<boolean>(true);
  const renderWindow = useMemo(() => {
    const s = Math.max(0, current - V_KEEP_LEFT);
    const e = Math.min(vedioInfoList.length - 1, current + V_KEEP_RIGHT);
    const set = new Set<number>();
    for (let i = s; i <= e; i++) set.add(i);
    return set;
  }, [current, vedioInfoList.length]);

  // 自定义进度
  const [progressMap, setProgressMap] = useState<Record<number, number>>({});
  const [durationMap, setDurationMap] = useState<Record<number, number>>({});
  const [dragging, setDragging] = useState(false);
  const [auditStatus, setAuditStatus] = useState<boolean>(false);
  const prevCurrentRef = useRef(0);
  // 统一管理所有 video 上下文，确保“只播一个”
  const videoCtxMapRef = useRef<Record<number, VideoCtx>>({});
  // 每个索引只做一次 iOS 点击播放（避免 onPlay 死循环）
  const primedRef = useRef<Record<number, boolean>>({});
  // 播放去抖，避免短时间多次 playOnly 叠加
  const playTimerRef = useRef<any>(null);
  // 新增：记录上一次真正播放的索引
  const lastPlayingRef = useRef<number>(-1);

  // 兜底：下载后的本地视频路径（wxfile://...）
  const [localSrcMap, setLocalSrcMap] = useState<Record<number, string>>({});
  const [downloadTried, setDownloadTried] = useState<Record<number, boolean>>(
    {}
  );

  // 进入横向全屏
  const handleEnterFullscreen = (idx: number) => {
    try {
      const ctx = getVideoCtx(idx);
      // 方向：90 = 横向（顺时针）
      // 注：iOS/Android 的支持略有差异，但微信视频组件均支持 0/90/-90
      (ctx as any).requestFullScreen?.({ direction: 90 });
      setFullscreenIdx(idx);
    } catch {}
  };

  // 切换播放/暂停（单击手势调用）
  const handleTogglePlay = (idx: number) => {
    if (auditStatus) return;
    const isPlaying = !!playingMap[idx];
    try {
      const ctx = getVideoCtx(idx);
      if (isPlaying) {
        // 只暂停当前，不重置进度
        ctx.pause();
        setPlayingMap((m) => ({ ...m, [idx]: false }));
      } else {
        // 统一入口，内部已做 iOS 去抖与只播一个
        playOnly(idx);
        setPlayingMap((m) => ({ ...m, [idx]: true }));
      }
    } catch {}
  };

  // 记录每个视频的原始宽高，用于计算高度与方向
  const [metaMap, setMetaMap] = useState<
    Record<number, { w: number; h: number }>
  >({});

  //  绑定/解绑网络监听，防止进入/退出页面后监听器堆积
  useEffect(() => {
    const handler = getNetWorkStatus;
    Taro.onNetworkStatusChange(handler);
    return () => {
      try {
        Taro.offNetworkStatusChange(handler);
      } catch {}
    };
  }, []);

  const getVideoCtx = (i: number): VideoCtx => {
    if (!videoCtxMapRef.current[i]) {
      videoCtxMapRef.current[i] = Taro.createVideoContext(`video-${i}`);
    }
    return videoCtxMapRef.current[i];
  };

  // hard 参数表示是否进行“硬回收”（含 seek(0)），避免频繁 seek 带来额外 I/O
  const pauseAllExcept = (keep: number, hard = false) => {
    Object.keys(videoCtxMapRef.current).forEach((k) => {
      const i = Number(k);
      if (i !== keep) {
        try {
          const ctx = videoCtxMapRef.current[i];
          ctx.pause();
          (ctx as any).stop?.(); // 彻底释放音轨
          if (hard) ctx.seek(0);
        } catch {}
      }
    });
  };

  //  仅保留窗口内（current±V_KEEP），其余索引的数据/上下文/临时文件引用统统裁掉
  const shrinkAround = (cur: number) => {
    const keepSet = new Set<number>();
    for (let i = Math.max(0, cur - V_KEEP_LEFT); i <= cur + V_KEEP_RIGHT; i++) {
      keepSet.add(i);
    }

    // 1) 回收 VideoContext + 停止 offscreen 播放
    Object.keys(videoCtxMapRef.current).forEach((k) => {
      const i = Number(k);
      if (!keepSet.has(i)) {
        try {
          const ctx = videoCtxMapRef.current[i];
          ctx.pause();
          (ctx as any).stop?.();
          // 断开 src 的动作通过“不渲染该 Video”来实现，确保组件真正 unmount
        } catch {}
        delete videoCtxMapRef.current[i];
      }
    });

    // 2) 裁剪各种 Map，只保留窗口内
    const filterMap = <T extends Record<number, any>>(m: T): T => {
      const n: any = {};
      Object.keys(m).forEach((k) => {
        const i = Number(k);
        if (keepSet.has(i)) n[i] = m[i];
      });
      return n;
    };
    setProgressMap((m) => filterMap(m));
    setDurationMap((m) => filterMap(m));
    setLocalSrcMap((m) => filterMap(m));
    setDownloadTried((m) => filterMap(m));
    setMetaMap((m) => filterMap(m));
    setPlayingMap((m) => filterMap(m));
    primedRef.current = filterMap(primedRef.current as any);
  };

  //跳转雪茄柜详情
  const gotoCigaCabinetDetail = (e: any, data: any) => {
    e.stopPropagation(); // 阻止冒泡
    e.preventDefault(); // 防止默认

    //判断网络状态，如果没有网络则不可点击
    if (!store.commonStore.networkStatus) {
      Taro.showToast({ title: netWorkErrorInfo, icon: 'none' });
      return;
    }
    if (
      data.contentCigarCabinetVo &&
      data.contentCigarCabinetVo.productShopPath
    ) {
      halfScreenJump(data.contentCigarCabinetVo.productShopPath, {
        onFail: (err) => {
          //打开失败回调
          Taro.showToast({
            title: '暂无商品信息，请稍后再试',
            icon: 'none',
          });
        },
        onReturn: ({ reason, extraData }) => {
          //关闭半屏回调
          console.log('return reason:', reason, extraData);
        },
      });
    } else {
      Taro.showToast({ title: '暂无商品信息，请稍后再试', icon: 'none' });
    }
  };

  // 仅播放指定索引；iOS 延时 play，避免“静音自动播”
  const playOnly = (i: number) => {
    if (auditStatus) return;
    // 先停其它
    pauseAllExcept(i);

    // 播放去抖
    if (playTimerRef.current) {
      clearTimeout(playTimerRef.current);
      playTimerRef.current = null;
    }

    playTimerRef.current = setTimeout(() => {
      try {
        const ctx = getVideoCtx(i);
        // iOS 一次性点击播放
        if (isIOS && !primedRef.current[i]) {
          primedRef.current[i] = true;
          try {
            ctx.pause();
          } catch {}
          setTimeout(() => {
            try {
              ctx.play();
              lastPlayingRef.current = i;
            } catch {}
          }, 30);
        } else {
          ctx.play();
          lastPlayingRef.current = i;
        }
      } catch {}
    }, PLAY_DEBOUNCE);
  };

  const onAnimFinish = (e: any) => {
    const idx = e.detail.current ?? current;
    prevCurrentRef.current = idx;
    // 动画结束再做重活：播放&预取
    Taro.nextTick(() => {
      if (!auditStatus) playOnly(idx);
    });
    if (idx >= vedioInfoList.length - PREFETCH_OFFSET) {
      loadNextPage();
    }
    //  每次滑动结束后做窗口收缩，释放 offscreen 资源
    shrinkAround(idx);
  };

  // 重置播放相关状态
  const resetPlaybackState = () => {
    setCurrent(0);
    setProgressMap({});
    setDurationMap({});
    setLocalSrcMap({});
    setDownloadTried({});
    setMetaMap({});
    setPlayingMap({});
    primedRef.current = {};
    prevCurrentRef.current = 0;

    //  彻底清掉已有的上下文
    Object.keys(videoCtxMapRef.current).forEach((k) => {
      const i = Number(k);
      try {
        const ctx = videoCtxMapRef.current[i];
        ctx.pause();
        (ctx as any).stop?.();
      } catch {}
      delete videoCtxMapRef.current[i];
    });
  };

  // 拉首条详情 + 第一页推荐（进入页面 & 下拉刷新时）
  const loadFirstScreen = async () => {
    if (!params.contentId || !params.contentKind || !params.contentType) return;

    setRefreshing(true);
    try {
      // 1) 首条详情
      const detailParams = {
        contentId: params.contentId,
        contentKind: params.contentKind,
        contentType: params.contentType,
        ucUserId: Taro.getStorageSync('userId')
          ? Taro.getStorageSync('userId')
          : '88888888',
      };
      const detailRes: any = await queryInfoFun(detailParams);
      // 已下架判断
      if (!detailRes) {
        setAuditStatus(true);
        Taro.showToast({ title: '该视频已删除！', icon: 'none' });
        setTimeout(() => {
          Taro.reLaunch({ url: '/pages/home/index' });
        }, 1000);
      } else if (detailRes.auditStatus === 0) {
        Taro.showToast({ title: '该视频已下架！', icon: 'none' });
        setAuditStatus(true);
        setTimeout(() => {
          Taro.reLaunch({ url: '/pages/home/index' });
        }, 1000);
        return;
      } else if (detailRes.auditStatus !== 2) {
        setAuditStatusVal(false);
      }
      setCollect(detailRes.collectStatus);

      setVedioInfoList([detailRes]);

      resetPlaybackState();

      // 2) 第一页推荐（DOWN）
      const { list: page0, empty } = await fetchRecommendPage(0);
      if (params.from === 'mine') {
      } else {
        setVedioInfoList([detailRes, ...page0]);
      }

      setPageNo(0);
      setHasMore(!empty); // 仅当为空时标记“没有更多”
      //  初始化后做一次窗口收缩
      shrinkAround(0);
    } catch (err) {
      console.error('loadFirstScreen error:', err);
    } finally {
      setRefreshing(false);
      Taro.stopPullDownRefresh();
    }
  };

  // 下拉刷新：拿“最新” -> scrollDirection=UP，从第0页开始
  const refreshLatestWithUP = async () => {
    if (!params.contentId || !params.contentKind || !params.contentType) return;

    setRefreshing(true);
    try {
      // 取当前顶部视频ID作为刷新锚点；没有就用路由里的
      const topId =
        (vedioInfoList.length > 0 && getItemId(vedioInfoList[0])) ||
        (params.contentId as string);

      // 重新拉首条详情（确保第一屏正确）
      const detailParams = {
        contentId: params.contentId,
        contentKind: params.contentKind,
        contentType: params.contentType,
        ucUserId: Taro.getStorageSync('userId')
          ? Taro.getStorageSync('userId')
          : '88888888',
      };
      const detailRes: any = await queryInfoFun(detailParams);
      // 已下架判断
      if (!detailRes) {
        setAuditStatus(true);
        Taro.showToast({ title: '该视频已删除！', icon: 'none' });
        setTimeout(() => {
          Taro.reLaunch({ url: '/pages/home/index' });
        }, 1000);
      } else if (detailRes.auditStatus === 0) {
        Taro.showToast({ title: '该视频已下架！', icon: 'none' });
        setAuditStatus(true);
        setTimeout(() => {
          Taro.reLaunch({ url: '/pages/home/index' });
        }, 1000);
        return;
      }
      // 拉“最新”的第一页推荐（UP）
      const upPage0: any = await fetchRecommendPage(0, topId, 'UP');

      // 用首条详情 + 最新推荐（覆盖原有推荐列表）
      setVedioInfoList([detailRes, ...upPage0]);

      // 重置分页（从0开始）、播放状态、滚动位置
      setPageNo(0);
      setHasMore(upPage0.length >= PAGE_SIZE); // 后续下滑仍按 DOWN 续拉
      resetPlaybackState();
      //
      shrinkAround(0);
    } catch (err) {
      console.error('refreshLatestWithUP error:', err);
    } finally {
      setRefreshing(false);
      Taro.stopPullDownRefresh();
    }
  };

  // 拉取推荐分页（仅返回数组及是否为空；外部决定 setState）
  const fetchRecommendPage = async (
    page: number,
    contentId: string = '',
    direction: 'UP' | 'DOWN' = 'DOWN'
  ) => {
    const req = {
      minContentVideoId: contentId ? contentId : (params.contentId as string),
      scrollDirection: direction,
      pageNum: page,
      pageSize: PAGE_SIZE,
      ucUserId: Taro.getStorageSync('userId')
        ? Taro.getStorageSync('userId')
        : '88888888',
    };
    const res: any = await videoRecommendFun(req);

    // 根据返回结构做兼容
    const list = Array.isArray(res) ? res : res?.videoRecommendVos || [];
    setMinContentVideoId(res?.minContentVideoId || '');

    return {
      list,
      empty: list.length === 0, // 为空才算没更多
    };
  };

  // 加载下一页
  const loadNextPage = async () => {
    if (loadingMore || !hasMore) return;
    setLoadingMore(true);
    try {
      const next = pageNo + 1;
      const { list: nextList, empty } = await fetchRecommendPage(
        next,
        minContentVideoId,
        'DOWN'
      );

      if (empty) {
        setHasMore(false); // 只有返回空，才显示“没有更多了”
      } else {
        setVedioInfoList((prev) => [...prev, ...nextList]);
        setPageNo(next);
        // 注意：不根据条数判断 hasMore，保持 true，直到某页返回空
      }
    } catch (e) {
      console.error('loadNextPage error:', e);
    } finally {
      setLoadingMore(false);
    }
  };

  useEffect(() => {
    loadFirstScreen();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [params.contentId, params.contentKind, params.contentType]);

  // 下拉刷新
  usePullDownRefresh(() => {
    if (!store.commonStore.networkStatus) {
      Taro.showToast({ title: netWorkErrorInfo, icon: 'none' });
      return;
    }
    refreshLatestWithUP();
  });

  useEffect(() => () => pauseAllExcept(-1, true), []);

  const onSwiperChange = (e: any) => {
    const idx = e.detail.current;
    setCurrent(idx);
    //  提前收缩窗口，避免越滑越大
    shrinkAround(idx);
  };

  // 工具：秒 ↔ 千分比
  const secToPct = (sec: number, dur: number) =>
    !dur ? 0 : Math.min(1000, Math.max(0, Math.round((sec / dur) * 1000)));
  const pctToSec = (pct: number, dur: number) =>
    !dur ? 0 : (pct / 1000) * dur;

  // 兜底下载：将远程 URL 下载为临时文件并切换 src
  const tryDownloadAndPlay = async (idx: number, url: string) => {
    //  仅在窗口内尝试下载，避免大量临时文件占用
    if (!renderWindow.has(idx)) return;
    if (downloadTried[idx]) return;
    setDownloadTried((m) => ({ ...m, [idx]: true }));
    try {
      const res = await Taro.downloadFile({ url });
      if (res.statusCode === 200) {
        const temp = res.tempFilePath;
        setLocalSrcMap((m) => ({ ...m, [idx]: temp }));
        Taro.nextTick(() => {
          setTimeout(() => {
            try {
              // 统一只播当前 idx，避免竞态
              playOnly(idx);
            } catch {}
          }, 0);
        });
        return;
      }
      throw new Error(`download status=${res.statusCode}`);
    } catch (err) {
      Taro.showToast({ title: '视频加载失败', icon: 'none', duration: 2000 });
    }
  };

  // 计算当前索引视频应当使用的高度与适配方式
  const getVideoStyleAndFit = (idx: number) => {
    const meta = metaMap[idx];
    if (!meta || !meta.w || !meta.h) {
      // 未拿到元数据前，给一个 16:9 的默认高度
      return {
        style: {
          width: '100%',
          height: `${Math.round((windowWidth * 9) / 16)}px`,
        },
        fit: 'contain' as 'cover' | 'contain' | 'fill',
      };
    }
    const { w, h } = meta;
    const isPortrait = h >= w; // 竖屏
    if (isPortrait) {
      // 竖屏：高度占满容器
      return {
        style: { width: '100%', height: '100%' },
        fit: 'cover' as const,
      };
    } else {
      // 横屏：宽度 100%，按比例计算高度，设置最小高度兜底
      const calcH = Math.max(MIN_HEIGHT_PX, Math.round(windowWidth * (h / w)));
      return {
        style: { width: '100%', height: `${calcH}px` },
        fit: 'contain' as const,
      };
    }
  };

  // 计算 slide-container 的高度（按方向扣除底部区域）
  const getSlideContainerHeight = (idx: number): string => {
    const meta = metaMap[idx];
    // 未拿到元数据前，按“竖屏方案”先占位，避免被底部遮挡
    if (!meta || !meta.w || !meta.h) {
      return 'calc(100% - 320rpx - env(safe-area-inset-bottom))';
    }
    const { w, h } = meta;
    const isPortrait = h >= w;
    // 竖屏：320rpx；横屏：280px
    return isPortrait
      ? 'calc(100% - 320rpx - env(safe-area-inset-bottom))'
      : 'calc(100% - 280px - env(safe-area-inset-bottom))';
  };

  const shareVedio = () => {
    if (!auditStatusVal) {
      showToast('视频审核暂未通过');
      return;
    }
  };

  //收藏
  const handleCollect = () => {
    if (!clickAble) return;
    clickAble = false;
    setTimeout(() => {
      clickAble = true;
    }, 2000);
    //判断网络状态，如果没有网络则不可点击
    if (!store.commonStore.networkStatus) {
      Taro.showToast({ title: netWorkErrorInfo, icon: 'none' });
      return;
    }
    //判断用户是否登录
    if (!isLoginFun()) return;
    //判断是否通过审核
    if (!auditStatusVal) {
      showToast('视频审核暂未通过');
      return;
    }
    //如果以收藏则取消收藏，否则收藏
    if (collect) {
      cancelCollectionFun({
        ucUserId: Taro.getStorageSync('userId'),
        ucLoginPhone: Taro.getStorageSync('mobile'),
        contentId: params.contentId,
        contentKind: params.contentKind,
        contentType: params.contentType,
      }).then((res: any) => {
        showToast('取消收藏成功');
      });
    } else {
      addCollectionFun({
        ucUserId: Taro.getStorageSync('userId'),
        ucLoginPhone: Taro.getStorageSync('mobile'),
        contentId: params.contentId,
        contentKind: params.contentKind,
        contentType: params.contentType,
      }).then((res: any) => {
        showToast('收藏成功');
      });
    }
    setCollect(!collect);
  };

  //跳转到个人中心
  const gotoUserCenter = (item: any) => {
    Taro.navigateTo({
      url: `/subPagesAccount/userCenter/index?contentKind=${item.contentKind}&&contentType=${item.contentType}&&userId=${item.userInfoVo.ucUserId}`,
    });
  };

  const gotoProductDetail = (data: any) => {
    //判断网络状态，如果没有网络则不可点击
    if (!store.commonStore.networkStatus) {
      Taro.showToast({ title: netWorkErrorInfo, icon: 'none' });
      return;
    }
    Taro.navigateTo({
      url: `/subPagesWiki/cigaDetail/index?sku=${data.cigarSku}`,
    });
  };

  //  长刷时自动“裁头”，防止 vedioInfoList/Map/上下文无限增长
  useEffect(() => {
    if (current > DROP_THRESHOLD) {
      setVedioInfoList((prev) => {
        const dropped = Math.min(DROP_BATCH, current);
        const next = prev.slice(dropped); // 裁掉前面若干项
        setCurrent((c) => c - dropped); // 视觉位置保持不跳

        // 工具：整体左移索引
        const shiftLeft = <T extends Record<number, any>>(m: T): T => {
          const n: any = {};
          Object.keys(m).forEach((k) => {
            const i = Number(k) - dropped;
            if (i >= 0) n[i] = (m as any)[k];
          });
          return n;
        };

        setProgressMap((m) => shiftLeft(m));
        setDurationMap((m) => shiftLeft(m));
        setLocalSrcMap((m) => shiftLeft(m));
        setDownloadTried((m) => shiftLeft(m));
        setMetaMap((m) => shiftLeft(m));
        setPlayingMap((m) => shiftLeft(m));

        const newCtx: Record<number, VideoCtx> = {};
        Object.keys(videoCtxMapRef.current).forEach((k) => {
          const i = Number(k) - dropped;
          if (i >= 0) newCtx[i] = videoCtxMapRef.current[k];
        });
        videoCtxMapRef.current = newCtx;

        primedRef.current = shiftLeft(primedRef.current as any);

        // 最后再做一次 shrink，确保只保留窗口
        Taro.nextTick(() => shrinkAround(Math.max(0, current - dropped)));

        return next;
      });
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [current]);

  useEffect(() => {
    if (auditStatus) {
      pauseAllExcept(-1, true); // 全停并 seek(0)
      setPlayingMap({});
    }
  }, [auditStatus]);

  const getImageSrc = (type: any) => {
    switch (type) {
      case '品牌方':
        return require('../../assert/imgs/user/pinpai.png');
      case '大咖':
        return require('../../assert/imgs/user/daka.png');
      case '雪茄吧':
        return require('../../assert/imgs/user/xuejiaba.png');
      case '侍咖师':
        return require('../../assert/imgs/user/shikashi.png');
      default: // 包括 null 的情况
        return null;
    }
  };
  return (
    <View
      className="video-detail-container"
      style={{
        paddingTop: `${store.commonStore.pageAreaTop}rpx`,
        height: `calc(100vh - ${store.commonStore.pageAreaTop}rpx)`,
      }}
    >
      <TitleBar showLeftBack theme="dark" />
      {
        <View className="video-swiper-wrap">
          <Swiper
            className="video-swiper"
            vertical
            current={current}
            onChange={onSwiperChange}
            onAnimationFinish={onAnimFinish}
            circular={false}
            indicatorDots={false}
            autoplay={false}
            skipHiddenItemLayout
            duration={260}
            easingFunction="linear"
            style={{ height: '100%' }}
          >
            {vedioInfoList.length > 0 &&
              vedioInfoList.map((item: any, idx: number) => {
                const inWindow = renderWindow.has(idx);

                const realSrc = localSrcMap[idx] || item.contentVideo;
                const contentTopic: any =
                  item.contentTopic &&
                  item.contentTopic.substring(1, item.contentTopic.length - 1);
                const contentTopicList: any =
                  contentTopic && contentTopic.split(',');
                const vf = getVideoStyleAndFit(idx);
                const isLandscape =
                  !!metaMap[idx]?.w &&
                  !!metaMap[idx]?.h &&
                  metaMap[idx].w > metaMap[idx].h;
                // 计算这个 idx 是否在全屏
                const isFs = fullscreenIdx === idx;

                return (
                  <SwiperItem key={idx}>
                    {/* FIX: 非窗口项不渲染 Video 与 footer，仅渲染轻量占位，降低内存/重排/事件负担 */}
                    {inWindow ? (
                      <>
                        <View
                          className="slide-container"
                          style={{ height: getSlideContainerHeight(idx) }}
                        >
                          <Video
                            id={`video-${idx}`}
                            key={`v-${getItemId(item) || idx}-${!!localSrcMap[idx]}`}
                            src={realSrc}
                            className="video-player"
                            autoplay={!auditStatus && idx === current}
                            muted={auditStatus || idx !== current}
                            enablePlayGesture={isIOS}
                            objectFit={vf.fit}
                            loop
                            controls={isFs && !auditStatus} // 关闭原生控制条，避免左下角按钮与底部重叠
                            showCenterPlayBtn={false}
                            enableProgressGesture={false}
                            // @ts-ignore
                            showProgress={false}
                            style={vf.style}
                            onLoadedMetaData={(e) => {
                              const detail: any = e.detail || {};
                              if (detail.width && detail.height) {
                                setMetaMap((m) => ({
                                  ...m,
                                  [idx]: { w: detail.width, h: detail.height },
                                }));
                              }
                              primedRef.current[idx] = false;
                              if (idx === current && !auditStatus)
                                playOnly(idx);
                            }}
                            onPlay={() => {
                              setPlayingMap((m) => ({ ...m, [idx]: true }));
                            }}
                            onPause={() => {
                              setPlayingMap((m) => ({ ...m, [idx]: false }));
                            }}
                            onTimeUpdate={(e) => {
                              if (idx !== current || dragging) return;
                              const { currentTime, duration } = e.detail as any;
                              setProgressMap((m) => ({
                                ...m,
                                [idx]: currentTime || 0,
                              }));
                              if (duration != null)
                                setDurationMap((m) => ({
                                  ...m,
                                  [idx]: duration || 0,
                                }));
                            }}
                            onFullscreenChange={(e) => {
                              const fs = (e?.detail as any)?.fullScreen;
                              setFullscreenIdx(fs ? idx : null);
                            }}
                            onError={() => {
                              if (item?.contentVideo)
                                tryDownloadAndPlay(idx, item.contentVideo);
                            }}
                          />

                          {isLandscape && (
                            <View
                              className="fullScreen-container"
                              onClick={() => handleEnterFullscreen(idx)}
                            >
                              <Image src={fullscreen} className="full-icon" />
                              <View className="paly-text">全屏播放</View>
                            </View>
                          )}

                          {/* 单击切换播放/暂停；如需双击点赞可以再加 onDoubleClick */}
                          <View
                            className="gesture-layer"
                            onClick={() => handleTogglePlay(idx)}
                          />
                          {!playingMap[idx] && (
                            <View
                              className="center-play-hint"
                              onClick={() => handleTogglePlay(idx)}
                            >
                              <Image
                                src="https://file.linkcook.cn/image/wineMiniProgram/home/play.png"
                                className="center-play-icon"
                              />
                            </View>
                          )}
                        </View>

                        {/*  footer 只在窗口内渲染，避免离屏的大量图片/按钮长期驻留 */}
                        <View
                          className="audio-footer"
                          style={{
                            bottom: store.commonStore.isIos
                              ? `${store.commonStore.safeAreaBottom}rpx`
                              : `${store.commonStore.safeAreaBottom + 20}rpx`,
                          }}
                        >
                          {(item?.contentCigarCabinetVo
                            ?.contentCigarCabinetZh ||
                            item?.contentCigarVo?.contentCigarZh) && (
                            <View
                              className="related-container"
                              onClick={() =>
                                gotoProductDetail(item.contentCigarVo)
                              }
                            >
                              {item?.contentCigarVo?.contentCigarZh && (
                                <View className="ciga-info">
                                  <Text className="ciga-product-title">
                                    雪茄
                                  </Text>
                                  <View className="line"></View>
                                  <Text className="ciga-name clamp1">
                                    {item.contentCigarVo.contentCigarBrand}{' '}
                                    {item.contentCigarVo.contentCigarZh}
                                  </Text>
                                </View>
                              )}
                              {item?.contentCigarCabinetVo
                                ?.contentCigarCabinetZh && (
                                <View
                                  className="ciga-info"
                                  onClick={(e) =>
                                    gotoCigaCabinetDetail(e, item)
                                  }
                                >
                                  <Text className="cigaCabinet-title">
                                    雪茄柜
                                  </Text>
                                  <View className="line"></View>
                                  <Text className="ciga-name clamp1">
                                    {
                                      item.contentCigarCabinetVo
                                        .contentCigarCabinetBrand
                                    }{' '}
                                    {
                                      item.contentCigarCabinetVo
                                        .contentCigarCabinetZh
                                    }
                                  </Text>
                                </View>
                              )}
                            </View>
                          )}

                          <View className="audio-title">
                            {item?.title}
                            {contentTopicList &&
                              contentTopicList.map((t: any, index: any) => (
                                <Text className="comment-topic" key={index}>
                                  #{t}#&nbsp;
                                </Text>
                              ))}
                            {(Array.isArray(item?.contentTopicList) &&
                              item.contentTopicList.join('#')) ||
                              ''}
                          </View>

                          <View className="audio-progress">
                            <Slider
                              className="slider-progress"
                              value={secToPct(
                                progressMap[idx] || 0,
                                durationMap[idx] || 0
                              )}
                              min={0}
                              max={1000}
                              step={1}
                              activeColor="rgba(255,255,255,0.5)"
                              backgroundColor="rgba(255,255,255,0.2)"
                              blockSize={14}
                              onChanging={(e) => {
                                setDragging(true);
                                const dur = durationMap[idx] || 0;
                                const sec = pctToSec(e.detail.value, dur);
                                setProgressMap((m) => ({ ...m, [idx]: sec }));
                              }}
                              onChange={(e) => {
                                const dur = durationMap[idx] || 0;
                                const sec = pctToSec(e.detail.value, dur);
                                try {
                                  const ctx = Taro.createVideoContext(
                                    `video-${idx}`
                                  );
                                  ctx.seek(sec);
                                } catch {}
                                setDragging(false);
                                if (!auditStatus) playOnly(idx);
                              }}
                            />
                          </View>

                          <View className="audio-protrait">
                            <View
                              className="protrait-infos"
                              onClick={() => gotoUserCenter(item)}
                            >
                              <Image
                                className="protrait-icon"
                                //  懒加载，降低离屏图片带宽与内存占用
                                lazyLoad
                                src={
                                  (item?.userInfoVo &&
                                    item.userInfoVo.ucAvatarUrl) ||
                                  ''
                                }
                              />
                              <View className="protrait-item">
                                <View>
                                  <Text className="audio-protrait-name">
                                    {(item?.userInfoVo &&
                                      item.userInfoVo.ucNickname) ||
                                      ''}
                                  </Text>
                                  {item?.userInfoVo && item.userInfoVo.tag && (
                                    <Image
                                      src={getImageSrc(item.userInfoVo.tag)}
                                      className="audio-brand"
                                      lazyLoad
                                    />
                                  )}
                                </View>
                                <View className="audio-protrait-date">
                                  {(item?.view || 0) + '浏览·'}
                                  {item?.publishTime &&
                                    item.publishTime.split(' ')[0]}
                                  {'·' + (item?.city || '')}
                                </View>
                              </View>
                            </View>
                            <View className="operate">
                              {auditStatusVal ? (
                                <View>
                                  <Button
                                    className="custom-share-wrapper"
                                    openType="share"
                                  >
                                    <Image
                                      className="icon"
                                      src={share}
                                      lazyLoad
                                    />
                                  </Button>
                                  <View>分享</View>
                                </View>
                              ) : (
                                <View>
                                  <Button
                                    className="custom-share-wrapper"
                                    onClick={shareVedio}
                                  >
                                    <Image
                                      className="icon"
                                      src={share}
                                      lazyLoad
                                    />
                                  </Button>
                                  <View>分享</View>
                                </View>
                              )}
                              <View onClick={handleCollect}>
                                <Image
                                  src={collect ? collectedIcon : collectIcon}
                                  className="icon"
                                  lazyLoad
                                />
                                <View>{collect ? '已收藏' : '收藏'}</View>
                              </View>
                            </View>
                          </View>
                        </View>
                      </>
                    ) : (
                      //  极简占位，避免布局抖动；不要带图片/按钮/复杂节点
                      <View className="video-placeholder" />
                    )}
                  </SwiperItem>
                );
              })}
          </Swiper>
        </View>
      }
      <StatusToast />
      {/* 也可按需做一个“加载中/没有更多”的浮层 */}
      {!hasMore && vedioInfoList.length > 0 && (
        <View className="list-nomore">没有更多了</View>
      )}
    </View>
  );
};

export default observer(VideoDetail);
